/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.ipti.br.tag.pdf;

import org.ipti.br.tag.bo.HbBO;
import org.ipti.br.tag.bo.WeightAndHeightBO;
import com.itextpdf.text.BaseColor;
import com.itextpdf.text.Chunk;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.Image;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.ColumnText;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfPageEventHelper;
import com.itextpdf.text.pdf.PdfWriter;
import org.ipti.br.tag.configuration.qualifiers.LocalCity;
import org.ipti.br.tag.entity.City;
import org.ipti.br.tag.entity.Human;
import org.ipti.br.tag.entity.Unity;
import org.ipti.br.tag.entity.WeightAndHeight;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.Serializable;
import java.text.Normalizer;
import java.util.Date;
import java.util.List;
import java.util.logging.Level;
import javax.ejb.Stateless;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.inject.Inject;
import javax.servlet.http.HttpServletResponse;
import org.ipti.br.tag.util.CalendarUtil;
import org.ipti.br.tag.util.LoggerUtil;
import org.ipti.br.tag.util.ServiceUtil;

/**
 *
 * @author luancorumba
 */
@Stateless
public class PrescriptionPDF implements Serializable{
    @Inject private WeightAndHeightBO weightAndHeightBO;
    @Inject private HbBO hbBO;
    @Inject
    @LocalCity
    private City city;
    
    private static final int DEFAULT_BUFFER_SIZE = 10240;
    private Font catFont = new Font(Font.FontFamily.TIMES_ROMAN, 16, Font.BOLD);
    private Font subFont = new Font(Font.FontFamily.TIMES_ROMAN, 14, Font.BOLD);
    private Font smallBold = new Font(Font.FontFamily.TIMES_ROMAN, 12, Font.BOLD);
    private Font textF = new Font(Font.FontFamily.TIMES_ROMAN, 16, Font.NORMAL);
    private Document document;
    private FacesContext facesContext;
    private ExternalContext externalContext;
    private Image logo;

    public void generate(FacesContext facesContext, Unity unity, List<Human> students, int concentration, Date consultation){
        String name = "Receituario - "+ unity.getName();
        name = Normalizer.normalize(name, Normalizer.Form.NFD);
        name = name.replaceAll("[\\W]", "");
        
        facesContext = ServiceUtil.getFacesContext();
        externalContext = facesContext.getExternalContext();
        
        String path = externalContext.getRealPath("resources/pdf/"+name+".pdf");
        
        this.make(path, students, concentration, consultation);
        this.send(facesContext,path);
    }
    
    private void make(String file, List<Human> humans, int concentration, Date consultation) {
        try {
            logo = Image.getInstance(externalContext.getRealPath("SLDI.jpg"));
            Rectangle layout = new Rectangle(PageSize.A4);
            layout.setBackgroundColor(BaseColor.WHITE);
            layout.setBorderColor(BaseColor.BLACK);
            layout.setBorderWidth(3);
            layout.setBorder(Rectangle.BOX);
            document = new Document(layout);
            PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(file));
            writer.setPageEvent(new Footer());
            document.open();
            addMetaData();
            WeightAndHeight wAh;
            for (Human human : humans) {
                wAh = weightAndHeightBO.getLastMeasure(human);
                if (wAh != null) {
                    for (int i = 0; i < 2; i++) {
                        addTitle();
                        addHead(human);
                        addContent(wAh, concentration, consultation);
                        document.newPage();
                    }
                }
            }
            document.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    private void addMetaData() {
        document.addTitle("Receituário");
        document.addSubject("Hb");
        document.addKeywords("Questionário, Anemnese, Hb, Anemia, TAG, IPTI");
        document.addAuthor("Instituto de Pesquisa em Tecnologia e Inovação - IPTI");
        document.addCreator("Tecnologia de Apoio a Gestão - TAG");
    }

    private void addTitle() throws DocumentException, IOException {
        
        PdfPTable top = new PdfPTable(2);
        logo.setAlignment(Image.ALIGN_LEFT);
        logo.scalePercent(25f);
        Chunk topC = new Chunk(logo,0,0,true);
        PdfPCell cell = new PdfPCell(logo);
        cell.setBorderWidth(0f);
        top.addCell(cell);
        
        Paragraph title = new Paragraph();
        Paragraph field = new Paragraph("Prefeitura Municipal de Santa Luzia do Itanhi",catFont);
        field.setAlignment(Paragraph.ALIGN_CENTER);
        title.add(field);
        title.add(Chunk.NEWLINE);
        field = new Paragraph("Secretatia Municipal de Saúde", subFont);
        field.setAlignment(Paragraph.ALIGN_CENTER);
        title.add(field);
        title.setAlignment(Paragraph.ALIGN_RIGHT);
        cell = new PdfPCell(title);
        cell.setBorderWidth(0f);
        top.addCell(cell);
        top.setWidths(new float[] {20f,70f});
        
        document.add(top);
        
        title = new Paragraph();
        addEmptyLine(title, 2);
        document.add(title);
    }
    
    public void addHead(Human human) throws DocumentException {
        Paragraph head = new Paragraph("Receituário", subFont);
        head.setAlignment(Paragraph.ALIGN_CENTER);
        document.add(head);
        
        head = new Paragraph();
        addEmptyLine(head, 1);
        document.add(head);
        
        head = new Paragraph(human.getName(),smallBold);
        head.setAlignment(Paragraph.ALIGN_LEFT);
        document.add(head);
    }
    
    private void addContent(WeightAndHeight wAh, int concentration, Date consultation) throws DocumentException, IOException {
        String recipie1,recipie2;
        if (wAh.getWeight() <= 30) {
            recipie1 = String.format("Sulfato Ferroso em gotas\n\n%d gotas por dia, 2 vezes ao dia (após almoço e jantar)",
                    Math.round((3*wAh.getWeight()*20)/concentration));
            recipie2 = String.format("Albendazol %d mg\n\n%d comprimido(s) (pode dissolver em copo com água ou suco)",
                    concentration, (concentration == 200) ? 2 : 1);
        } else {
            recipie1 = "Sulfato Ferroso em comprimidos\n\n 2 comprimidos por dia, 2 vezes ao dia (um após almoço e outro após o jantar)";
            recipie2 = String.format("Albendazol %d mg\n\n%d comprimido(s)",
                    concentration, (concentration == 200) ? 2 : 1);
        }
        
        Paragraph msg = new Paragraph();
        addEmptyLine(msg, 5);
        document.add(msg);
        
        msg = new Paragraph(recipie1, textF);
        msg.setAlignment(Paragraph.ALIGN_CENTER);
        document.add(msg);
        
        msg = new Paragraph();
        addEmptyLine(msg, 5);
        document.add(msg);
        
        msg = new Paragraph(recipie2, textF);
        msg.setAlignment(Paragraph.ALIGN_CENTER);
        document.add(msg);
        
        msg = new Paragraph();
        addEmptyLine(msg,8);
        document.add(msg);
        
        msg = new Paragraph(city.getName()+", "+CalendarUtil.getFormatedDate(consultation));
        msg.setAlignment(Paragraph.ALIGN_LEFT);
        document.add(msg);
    }

    private void addEmptyLine(Paragraph paragraph, int number) {
        for (int i = 0; i < number; i++) {
            paragraph.add(new Paragraph(" "));
        }
    }
    
    private void send(FacesContext facesContext, String path){
        HttpServletResponse response = (HttpServletResponse) externalContext.getResponse();

        File file = new File(path);
        BufferedInputStream input = null;
        BufferedOutputStream output = null;

        try {
            input = new BufferedInputStream(new FileInputStream(file), DEFAULT_BUFFER_SIZE);
            response.reset();
            response.setHeader("Content-Type", "application/pdf");
            response.setHeader("Content-Length", String.valueOf(file.length()));
            response.setHeader("Content-Disposition", "inline; filename=\"" + file.getName() + "\"");
            output = new BufferedOutputStream(response.getOutputStream(), DEFAULT_BUFFER_SIZE);
            byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
            int length;
            while ((length = input.read(buffer)) > 0) {
                output.write(buffer, 0, length);
            }
            output.flush();
        } catch (Exception ex) {
            ex.printStackTrace();
            LoggerUtil.log("SimpleFrequencyBean:export", Level.SEVERE, "Não enviou", ex);
        } finally {
            try {
                output.close();
                input.close();
            } catch (IOException e) {
                e.printStackTrace();
                LoggerUtil.log("SimpleFrequencyBean:export", Level.SEVERE, "Não fechou", e);
            }
        }
        facesContext.responseComplete();
        file.delete();
    }
    
    public class Footer extends PdfPageEventHelper {
        
        @Override
        public void onEndPage(PdfWriter writer, Document document) {
            Rectangle rect = writer.getPageSize();
            ColumnText.showTextAligned(writer.getDirectContent(),
                    Element.ALIGN_CENTER, new Phrase("Voltando à consulta, favor trazer esta receita",smallBold),
                    (rect.getLeft() + rect.getRight()) / 2, rect.getBottom() + 28, 0);
        }
    }
}
